from enum import IntEnum
import wx
from app_analysevar import _insc
import sys
from collections import OrderedDict
from wxPopupError import popuperror
from htmltool import htmltabrowfakelist, htmlparag, htmllist, htmltabrow, htmlparInformTab

class CompareA2lInform:
    @popuperror
    def compare(self, text_1, text_2, param_order = ''):
        print('waiting ...')
        ins = _insc.IncaControl()
        ins.init(expinit = False)
        incadb = ins.inca.GetCurrentDataBase()
        assert incadb, '无法连接到 INCA数据库 '
        data = {
            'a2lname': (text_1, text_2),
            'a2lpath': ['', ''],
            'a2lincapath': ['', ''],  # a2l 在INCA数据库中的路径
            'names_m': [set(), set()],  # a2l 0/1 独有的测量量名称
            'names_c': [set(), set()],  # a2l 0/1 独有的标定量名称
            'names_a': [set(), set()],  # a2l 0/1 独有的轴名称
            'names': [set(), set()],  # a2l 0/1 独有的变量名称
            'newinform': dict(),  # a2l 0 新增变量的信息  # name : datatuple # (单位,下限,上限,精度,地址,数据类型,备注)
            'newparamserror': []  # 查找信息时出错的变量
        }
        mall = [set(), set()]
        call = [set(), set()]
        aall = [set(), set()]
        multi_incaitem = [False, False]
        order = param_order.split('\n')
        print('read a2l ...')
        for index, text in enumerate([text_1, text_2]):
            incaitems = incadb.BrowseItem(text)
            assert incaitems, '在INCA数据库中没找到"%s"' % text
            incaitemslen = len(incaitems)
            if incaitemslen == 1:
                tempitem = incaitems[0]
                if tempitem.IsAsap2Item() and tempitem.IsAsap2Project():
                    data['a2lincapath'][index] = tempitem.GetNameWithPath()
                    a2l = tempitem.Asap2Module()
                else:
                    assert False, '"%s" 不是A2L项目' % text
            elif incaitemslen > 1:
                textdict = {x.GetNameWithPath(): x for x in incaitems}
                textlist = sorted(textdict.keys())
                with AlertUserChseA2lItemWin(a2ltext=text, items=textlist) as chsewin:
                    rslt = chsewin.ShowModal()
                multi_incaitem[index] = True
                data['a2lincapath'][index] = textlist[rslt]
                tempitem = textdict[textlist[rslt]]
                if tempitem.IsAsap2Item() and tempitem.IsAsap2Project():
                    data['a2lpath'][index] = tempitem
                    a2l = tempitem.Asap2Module()
                else:
                    assert False, '"%s" 不是A2L项目' % text
            else:
                assert False, '在INCA数据库中没找到"%s"' % text

            mall[index] = set(a2l.GetAllElementNamesOfType('allMeasurements'))
            call[index] = set(a2l.GetAllElementNamesOfType('allCharacteristics'))
            aall[index] = set(a2l.GetAllElementNamesOfType('allAxisPoints'))

        data['names_m'] = (mall[0] - mall[1], mall[1] - mall[0])  # a2l 0/1 独有的测量量名称
        data['names_c'] = (call[0] - call[1], call[1] - call[0])  # a2l 0/1 独有的标定量名称
        data['names_a'] = (aall[0] - aall[1], aall[1] - aall[0])  # a2l 0/1 独有的轴名称
        data['names'] = (
            data['names_m'][0] | data['names_c'][0] | data['names_a'][0],
            data['names_m'][1] | data['names_c'][1] | data['names_a'][1]
        )

        incaitems = incadb.BrowseItem(data['a2lname'][0])
        if multi_incaitem[0]:
            tempitem = {x.GetNameWithPath(): x for x in incaitems}[data['a2lincapath'][0]]
        else:
            tempitem = incaitems[0]
        a2l = tempitem.Asap2Module()
        templen = len(data['names'][0])
        print('read params ...')
        for i, name in enumerate(data['names'][0]):
            try:
                if name in data['names_m'][0]:
                    elema2l = a2l.GetMeasurementNamed(name)
                elif name in data['names_c'][0]:
                    elema2l = a2l.GetCharacteristicNamed(name)
                else:
                    elema2l = a2l.GetAxisPointNamed(name)
                temp = ins.geta2ldata(elema2l)
                data['newinform'][name] = temp
            except:
                data['newparamserror'].append(name)

        print('almost ...')
        return self.getcompareA2lHtml(data, order)

    def getcompareA2lHtml(self, data, order:list[str]):
        orderlen = len(order)
        def sort_by_order(item):
            try:
                l = order.index(item)
            except ValueError:
                l = orderlen
            return l
        parag = OrderedDict()
        parag['overview'] = HTML_CompareA2l_Overview.format(a2l0=data['a2lname'][0], a2l1=data['a2lname'][1],
                                                            a2l0_path=data['a2lpath'][0], a2l1_path=data['a2lpath'][1],
                                                            newnum=len(data['names'][0]), delnum=len(data['names'][1]),
                                                            errnum0=len(data['newparamserror']))
        
        parag['newparams'] = HTML_CompareA2l_Newparams.format(
            htmltabrowfakelist(sorted(sorted(data['names'][0]), key=sort_by_order), ref=True))
        
        parag['delparams'] = HTML_CompareA2l_Delparams.format(
            htmltabrowfakelist(sorted(sorted(data['names'][1]), key=sort_by_order), ref=False))
        
        informstr = htmlparInformTab(data['newinform'], 
                                     sorted(sorted(data['newinform'].keys()), key=sort_by_order))
        parag['newinform'] = HTML_CompareA2l_Newinform.format(informstr)

        errorstr = '新A2L的错误变量:<br/>\n{0}\n'.format(
            htmllist(sorted(sorted(data['newparamserror']), key=sort_by_order)))
        parag['error'] = HTML_CompareA2l_Error.format(errorstr)

        return HTML_CompareA2l_Main.format(body=''.join(parag.values()), h2style='{background-color:#B0E0E6;\npadding:8px;}\n')


class CompareA2lWin(wx.Frame):
    """比对A2L信息"""

    def __init__(self, parent, mainobj):
        wx.Frame.__init__(self, parent=parent, title='比对A2L信息',
                          size=(700, 350), style=wx.DEFAULT_FRAME_STYLE | wx.FRAME_FLOAT_ON_PARENT)
        self.mainobj = mainobj
        self.SetBackgroundColour(wx.Colour(200, 210, 210))

        self.pl = wx.Panel(self, size=(700, 350))
        self.inf_1 = wx.StaticText(self.pl, label='INCA中的数据集名称(新A2L):', style=wx.ALIGN_CENTRE_HORIZONTAL)
        self.inf_2 = wx.StaticText(self.pl, label='INCA中的数据集名称(旧A2L):', style=wx.ALIGN_CENTRE_HORIZONTAL)
        self.text_1 = wx.TextCtrl(self.pl)
        self.text_2 = wx.TextCtrl(self.pl)
        self.text_log = wx.TextCtrl(self.pl, style=wx.TE_MULTILINE | wx.TE_READONLY, size=(80, 80))
        self.bt = wx.Button(self.pl, label='开始比对', size=(80, 40))

        self.sizer = wx.GridBagSizer(5, 10)
        self.sizer.Add(self.inf_1, pos=(0, 0), span=(1, 1), flag=wx.TOP | wx.LEFT, border=10)
        self.sizer.Add(self.text_1, pos=(0, 1), span=(1, 1), flag=wx.EXPAND | wx.RIGHT | wx.TOP, border=10)
        self.sizer.Add(10, 10, pos=(1, 0), span=(1, 1), flag=wx.EXPAND)
        self.sizer.Add(self.inf_2, pos=(2, 0), span=(1, 1), flag=wx.TOP | wx.LEFT, border=10)
        self.sizer.Add(self.text_2, pos=(2, 1), span=(1, 1), flag=wx.EXPAND | wx.RIGHT, border=10)
        self.sizer.Add(10, 10, pos=(3, 0), span=(1, 1), flag=wx.EXPAND)
        self.sizer.Add(self.bt, pos=(4, 1), span=(1, 1), flag=wx.ALL, border=5)
        self.sizer.Add(10, 10, pos=(5, 0), span=(1, 1), flag=wx.EXPAND)
        self.sizer.Add(self.text_log, pos=(6, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL, border=5)

        self.sizer.AddGrowableCol(1)
        self.pl.SetSizer(self.sizer)
        self.Bind(wx.EVT_BUTTON, self.on_button, self.bt)

        self.inf_1.Refresh()
        self.inf_2.Refresh()
        self.Centre()
        self.Show()

    def on_button(self, event):
        self.mainobj.set_stdout(self.text_log)
        text_1 = self.text_1.GetValue()
        text_2 = self.text_2.GetValue()
        if not text_1 or not text_2:
            return
        self.bt.Disable()
        with CompareA2l_RegulateParOrderWin(parent=self, mainobj=self.mainobj, text_1=text_1, text_2=text_2) as orderwin:
            orderwin.ShowModal()
        self.bt.Enable()
        self.mainobj.unset_stdout(self.text_log)

class CompareA2l_RegulateParOrderWin(wx.Dialog):
    def __init__(self, parent, mainobj, text_1, text_2):
        wx.Dialog.__init__(self, parent=parent, title='定义变量显示顺序', size=(500, 700), style=wx.STAY_ON_TOP | wx.CAPTION)
        self.mainobj = mainobj
        self.text_1 = text_1
        self.text_2 = text_2
        self.SetBackgroundColour(wx.Colour(200, 210, 210))

        self.pl = wx.Panel(self)#, size=(700, 350))
        self.inf = wx.StaticText(self.pl, label='如果需要, 定义变量显示顺序, 将变量名称复制到下面区域, \n\
                                 以换行为分隔', style=wx.ALIGN_CENTRE_HORIZONTAL)
        self.text = wx.TextCtrl(self.pl, style = wx.TE_MULTILINE)
        self.bt = wx.Button(self.pl, label='开始比对', size=(80, 40))
        self.bt_cancel = wx.Button(self.pl, label='取消', size=(80, 40))

        self.sizer = wx.GridBagSizer(2, 5)
        self.sizer.Add(self.inf, pos=(0, 0), span=(1, 1), flag=wx.TOP | wx.LEFT, border=10)
        self.sizer.Add(self.text, pos=(1, 0), span=(1, 1), flag=wx.EXPAND | wx.RIGHT | wx.TOP, border=10)
        self.sizer.Add(10, 10, pos=(2, 0), span=(1, 1), flag=wx.EXPAND)
        self.sizer.Add(self.bt, pos=(3, 0), span=(1, 1), flag=wx.ALL, border=5)
        self.sizer.Add(self.bt_cancel, pos=(3, 1), span=(1, 1), flag=wx.ALL, border=5)
        self.sizer.Add(10, 10, pos=(4, 0), span=(1, 1), flag=wx.EXPAND)
        self.sizer.AddGrowableCol(0)
        self.sizer.AddGrowableRow(1)
        self.pl.SetSizer(self.sizer)
        self.Bind(wx.EVT_BUTTON, self.on_button, self.bt)
        self.Bind(wx.EVT_BUTTON, self.on_cancel, self.bt_cancel)
        self.inf.Refresh()
        self.Centre()
        self.Show()

    def on_cancel(self, event):
        self.Destroy()

    def on_button(self, event):
        self.bt.Disable()
        self.Show(False)
        parorder = self.text.GetValue().strip()
        myhtml = CompareA2lInform().compare(self.text_1, self.text_2, parorder)
        wx.CallAfter(self.mainobj.gui.showhtml, myhtml)
        print('done ...')
        self.EndModal(0)

class AlertUserChseA2lItemWin(wx.Dialog):
    "在INCA中找到多个A2L项目时，提醒用户选择其中一个"

    def __init__(self, parent=None, title='选择一个A2l项目', mainobj=None, a2ltext='', items=()):
        wx.Dialog.__init__(self, parent=parent, title=title, size=(500, 200), style=wx.STAY_ON_TOP | wx.CAPTION)
        self.mainobj = mainobj
        self.items = items
        self.SetBackgroundColour(wx.Colour(200, 210, 210))

        self.pl = wx.Panel(self, size=(500, 200))
        self.alerttext = wx.StaticText(self.pl, label='"%s"\n在INCA中找到多个A2L项目,请选择其中一个:' % a2ltext,
                                       style=wx.ALIGN_CENTRE_HORIZONTAL)
        self.choice = wx.Choice(self.pl, choices=items)
        self.bt = wx.Button(self.pl, label='确认', size=(60, 40))

        self.sizer = wx.GridBagSizer(5, 10)
        self.sizer.Add(self.alerttext, pos=(0, 0), span=(1, 2), flag=wx.ALL | wx.EXPAND, border=10)
        self.sizer.Add(self.choice, pos=(1, 0), span=(1, 2), flag=wx.ALL | wx.EXPAND, border=10)
        self.sizer.Add(self.bt, pos=(2, 1), span=(1, 1), flag=wx.ALL, border=5)
        self.sizer.AddGrowableCol(0)
        self.pl.SetSizer(self.sizer)

        self.Bind(wx.EVT_BUTTON, self.on_button, self.bt)

        self.Centre()

    def on_button(self, event):
        text = self.choice.GetStringSelection()
        if text:
            index = self.items.index(text)
            self.EndModal(index)


########################################## HTML ####################################################

HTML_CompareA2l_Main = """<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="author" content="XiePeng">
<title>A2L比对信息</title>
<style type="text/css">
h2 {h2style}
</style>
</head>
<body>
{body}
</body>
</html>
"""

HTML_CompareA2l_Overview = """
<p>
<h2>总览</h2>
<ul>
<li><b>新A2L</b>: {a2l0}<br/>{a2l0_path}</li>
<li><b>旧A2L</b>: {a2l1}<br/>{a2l1_path}</li>
<li><b>新增变量</b>: {newnum} 个</li>
<li><b>删除变量</b>: {delnum} 个</li>
<li color="#DC143C"><b>新A2L出错的变量</b>: <strong>{errnum0}</strong> 个</li>
<li><b>索引</b></li>
    <ul>
    <li><a href="#newparams">新增变量</a></li>
    <li><a href="#delparams">删除变量</a></li>
    <li><a href="#newinform">新增变量信息</a></li>
    <li><a href="#error">错误变量</a></li>
    </ul>
</ul>
</p>
"""
HTML_CompareA2l_Newparams = """
<p>
<h2><a name="newparams">新增变量</a></h2>
<dl>
<dt></dt>
    <dd>
    {0}
    </dd>
</dl>
</p>
"""
HTML_CompareA2l_Delparams = """
<p>
<h2><a name="delparams">删除变量</a></h2>
<dl>
<dt></dt>
    <dd>
    {0}
    </dd>
</dl>
</p>
"""
HTML_CompareA2l_Newinform = """
<p>
<h2><a name="newinform">新增变量信息</a></h2>
<dl>
<dt></dt>
    <dd>
    {0}
    </dd>
</dl>
</p>
"""
HTML_CompareA2l_Error = """
<p>
<h2><a name="error">错误变量</a></h2>
{0}
</p>
"""
